package com.hsck.order.kds.base.utils

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type

/**
 * 1,把json转换成Object<br></br>
 * 2,把Object转换成json<br></br>
 * 3,该方法主要功能是将json字符串转换成指定类型的对象<br></br>
 * @author  isnoam
 */
class GsonUtils {
    companion object {
        /**
         * 工具类对象<br></br>
         * （单例）
         */
        private val gsonUtils: GsonUtils = GsonUtils()

        /**
         * Gson对象
         */
        private val gson = Gson()
        val instance: GsonUtils
            /**
             * 对外提供静态公有的方法
             *
             * @return 本类对象
             */
            get() = gsonUtils

        /**
         * 1，该方法主要功能是将json字符串转换成Java类对象
         *
         * @param json
         * json字符串
         * @param cls
         * Java类的字节码对象
         * @return 解析后的Java类对象
         * @throws Exception
         * 如果解析中出了问题，或者是json不完整都会抛出这个异常信息
         */
        @Throws(Exception::class)
        fun <T> j2O(json: String?, cls: Class<T>?): T {
            return gson.fromJson<T>(json, cls)
        }

        /**
         * 2，该方法主要功能是将Java类对象转换成json字符串
         *
         * @param obj
         * Java对象
         * @return json字符串
         */
        fun o2J(obj: Any?): String {
            return gson.toJson(obj)
        }

        /**
         * 3,该方法主要功能是将json字符串转换成指定类型的对象
         *
         * @param json
         * json字符串
         * @param typeOfT
         * 指定类型
         * @return 指定类型的对象
         */
        @Throws(Exception::class)
        fun <T> j2T(json: String?, typeOfT: Type?): T {
            return gson.fromJson<T>(json, typeOfT)
        }

        /**
         * 将JSON字符串转换为Any类型。
         *
         * @param value 要转换回Any类型的JSON字符串。
         * @return 从JSON字符串反序列化得到的Any类型。
         */
        fun toAny(value: String): Any {
            val type = object : TypeToken<Any>() {}.type
            return gson.fromJson(value, type)
        }


        /**
         * 从JSON对象中移除指定字段以及指定名称的数组、List和对象
         *
         * @param json JSON字符串
         * @param fields 要移除的字段名集合
         * @return 移除指定字段后的JSON字符串
         */
        fun removeFieldsFromJson(json: String, fields: Set<String>): String {
            val mapper: ObjectMapper = jacksonObjectMapper()
            val rootNode: JsonNode = mapper.readTree(json)

            // 递归移除字段
            removeFieldsRecursively(rootNode, fields)

            return mapper.writeValueAsString(rootNode)
        }


        /**
         * 递归移除JSON节点中的指定字段以及指定名称的数组、List和对象
         *
         * @param node 当前JSON节点
         * @param fields 要移除的字段名集合
         */
        private fun removeFieldsRecursively(node: JsonNode, fields: Set<String>) {
            if (node.isObject) {
                val objectNode = node as ObjectNode

                // 获取所有字段名称
                val fieldNames = objectNode.fieldNames().asSequence().toList()

                // 移除指定字段
                fields.forEach { objectNode.remove(it) }

                // 递归处理子节点
                fieldNames.forEach { fieldName ->
                    if (fieldName !in fields) { // 避免重复递归已删除的字段
                        removeFieldsRecursively(objectNode.get(fieldName), fields)
                    }
                }
            } else if (node.isArray) {
                node.forEach { arrayNodeElement ->
                    removeFieldsRecursively(arrayNodeElement, fields)
                }
            }
        }
    }
}